home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS14.ADF
/
Clocks
/
sClock
/
sClock.s
< prev
Wrap
Text File
|
1989-01-28
|
17KB
|
551 lines
* Sprite Clock
*
* This is a very simple clock that uses a sprite as it's display medium.
* It displays the time every minute for a couple seconds and then the sprite
* disappears. The time is displayed in 12-hr. format; you'll have to figure
* out if it is AM or PM yourself.
* It is useful if you are working on different screens alot since a sprite
* will appear in front of any screen.
* I had to design the numbers myself and I used alot of tricks to compress
* the space their data would have taken so that the clock will remain small.
* I would think that there is some way to take advantage of the fonts already
* in the system but I did not know enough about the form of the font in
* memory and how to access that data so that it could be used.
* Alot of different techniques are used in order to load the numerals into
* memory and I would think they would prove educational to someone.
* At this time this clock can not be terminated once it is started.
* I don't mind this since it takes up very little memory. This program
* could be given another port and a close message could be sent to it by
* another program or by something like the workbench menus if they where
* properly altered.
* Code size: 820 bytes
* minumum stack: 1600 bytes
* Running size: 6312 bytes
* I do not think it will work from the workbench in it's current version.
* Darrel Schneider
************************************************************************
NOPAGE
NOLIST
LLEN 132
; INCLUDE "exec/types.i"
; INCLUDE "exec/ables.i"
; INCLUDE "exec/memory.i"
; INCLUDE "devices/timer.i"
* the following equates take the place of the info in the above files
MP_SIZE: EQU $22
MP_SIGBIT: EQU $F
MEMF_CLEAR: EQU $10000
MEMF_PUBLIC: EQU $1
MEMF_CHIP: EQU $2
NT_MSGPORT: EQU $4
NT_MESSAGE: EQU $5
IOTV_SIZE: EQU $28
LN_TYPE: EQU $8
LN_NAME: EQU $A
IO_DEVICE: EQU $14
IO_UNIT: EQU $18
IO_COMMAND: EQU $1C
IO_SIZE: EQU $20
MN_REPLYPORT: EQU $E
TR_ADDREQUEST: EQU $9
TR_GETSYSTIME: EQU $A
UNIT_VBLANK: EQU $1
TV_SECS: EQU $0
TV_MICRO: EQU $4
XREF _AbsExecBase
XREF _LVOOpenLibrary
XREF _LVOCloseLibrary
XREF _LVOAllocMem
XREF _LVOFreeMem
XREF _LVOAllocSignal
XREF _LVOFreeSignal
XREF _LVOAddPort
XREF _LVORemPort
XREF _LVOOpenDevice
XREF _LVOCloseDevice
XREF _LVODoIO
XREF _LVOSendIO
XREF _LVOWaitIO
XREF _LVOFindTask
XREF _LVOGetSprite
XREF _LVOChangeSprite
XREF _LVOMoveSprite
XREF _LVOFreeSprite
LIST
Temp: EQUR d2
LoopCount: EQUR d2
Secs: EQUR d3
Micros: EQUR d4
AndMask: EQUR d5
Timer_Port: EQUR d6
GraphicsBase: EQUR d7
BufferPTR: EQUR a2
SimpleSpritePTR: EQUR a3
NewDataPTR: EQUR a4
Time_ReqPTR: EQUR a5
********** open libraries ***********
movea.l _AbsExecBase,a6
lea GraphicsName(pc),a1
moveq.l #0,d0
jsr _LVOOpenLibrary(a6)
tst.l d0
bne.s NOAbortOpenLibrary ;V
rts ;quit
NOAbortOpenLibrary:
move.l d0,GraphicsBase
********** create timer port **********
;get a signal bit
moveq.l #-1,d0
jsr _LVOAllocSignal(a6)
move.l d0,d2
bmi.l AbortCreateTimer1 ; if -1 AllocSignal failed so abort
; alloc port structure
moveq.l #MP_SIZE,d0
move.l #(MEMF_CLEAR!MEMF_PUBLIC),d1
jsr _LVOAllocMem(a6)
move.l d0,Timer_Port
bne.s skipAbortCode ;V it was allocated so skip the abort code
; AllocMem failed so clean up and then abort
move.l d2,d0
jsr _LVOFreeSignal(a6)
bra.l AbortCreateTimer2 ; if 0 AllocMem failed so abort
skipAbortCode:
; fill port fields
move.l Timer_Port,a2
addq.l #8,a2 ; a2 = &LN_TYPE
move.w #((NT_MSGPORT<<8)+Priority),(a2)+
; the last instruction does the next two
; move.b #NT_MSGPORT,(a2)+ ; LN_TYPE
; move.b #Priority,(a2)+ ; LN_PRI
lea TimerPortName(pc),a1
move.l a1,(a2)+ ; LN_NAME gets &TimerPortName
; this instruction is done by the next one since it is a move.w
; clr.b (a2)+ ; #PA_SIGNAL -> MP_FLAGS
move.w d2,(a2)+ ; MP_SIGBIT
moveq.l #0,d0
movea.l d0,a1
jsr _LVOFindTask(a6)
move.l d0,(a2) ; MP_SIGTASK
; add the port
movea.l Timer_Port,a1
jsr _LVOAddPort(a6)
bra.s SkipAbortSection ;V
*******************************************************************************
************************** TERMINATION SECTION *****************************
AbortNewDataAlloc:
moveq.l #0,d0
move.w 10(SimpleSpritePTR),d0
exg a6,GraphicsBase
jsr _LVOFreeSprite(a6)
exg a6,GraphicsBase
AbortGetSprite:
moveq.l #IOTV_SIZE,d4
adda.l d4,Time_ReqPTR
adda.l d4,Time_ReqPTR
moveq.l #1,d3
bra.s BEGINCloseDeviceLOOP ;V
AbortOpenDevice:
subq.l #1,d3
beq.s SKIPCloseDeviceLOOP ;V
moveq.l #0,d3
BEGINCloseDeviceLOOP:
; close timer device
suba.l d4,Time_ReqPTR
lea (Time_ReqPTR),a1
jsr _LVOCloseDevice(a6)
dbra d3,BEGINCloseDeviceLOOP ;^
SKIPCloseDeviceLOOP:
; deallocate Time_Req structure
moveq.l #-1,d3
movea.l Time_ReqPTR,a1
moveq.l #1,d0
DeallocateLOOP:
move.b d3,LN_TYPE(Time_ReqPTR)
move.l d3,IO_DEVICE(Time_ReqPTR)
move.l d3,IO_UNIT(Time_ReqPTR)
adda.l d4,Time_ReqPTR
dbra d0,DeallocateLOOP
moveq.l #IOTV_SIZE*2,d0
jsr _LVOFreeMem(a6)
AbortTime_ReqAlloc:
; close timer port
movea.l Timer_Port,a1
jsr _LVORemPort(a6)
movea.l Timer_Port,a2
; d3 = -1
move.b d3,LN_NAME(a2)
move.l d3,(a2) ; LH_HEAD
move.l MP_SIGBIT(a2),d0
jsr _LVOFreeSignal(a6)
movea.l Timer_Port,a1
moveq.l #MP_SIZE,d0
jsr _LVOFreeMem(a6)
AbortCreateTimer2:
AbortCreateTimer1:
move.l GraphicsBase,a1
jsr _LVOCloseLibrary(a6)
moveq.l #0,d0
rts
********************* END OF TERMINATION SECTION ***************************
****************************************************************************
SkipAbortSection:
********** initialize timerequest struct ***********
;alloc timerequest structure
moveq.l #IOTV_SIZE*2,d0
move.l #(MEMF_CLEAR!MEMF_PUBLIC),d1
jsr _LVOAllocMem(a6)
tst.l d0
beq.s AbortTime_ReqAlloc
movea.l d0,Time_ReqPTR
move.w #((NT_MESSAGE<<8)+Priority),LN_TYPE(Time_ReqPTR)
; The previous instruction actually does the next two.
; move.b #NT_MESSAGE,LN_TYPE(Time_ReqPTR)
; move.b #Priority,LN_PRI(Time_ReqPTR)
move.l Timer_Port,MN_REPLYPORT(Time_ReqPTR)
; cleared in the AllocMem call
; clr.w IO_FLAGS(Time_ReqPTR) ; this also zeros IO_ERROR
move.w #TR_ADDREQUEST,IO_COMMAND(Time_ReqPTR)
moveq.l #IOTV_SIZE,d0
move.w #((NT_MESSAGE<<8)+Priority),LN_TYPE(Time_ReqPTR,d0.w)
move.w #TR_GETSYSTIME,IO_COMMAND(Time_ReqPTR,d0.w)
********** open vblank timer device **************
moveq.l #1,d3
moveq.l #IOTV_SIZE,d4
OpenDeviceLOOP:
lea TimerName(pc),a0
lea (Time_ReqPTR),a1
moveq.l #UNIT_VBLANK,d0
moveq.l #0,d1
jsr _LVOOpenDevice(a6)
tst.l d0
bne.l AbortOpenDevice
adda.l d4,Time_ReqPTR
dbra d3,OpenDeviceLOOP
sub.l d4,Time_ReqPTR
sub.l d4,Time_ReqPTR
********** initialize the Sprite *******************
lea SimpleSprite(pc),SimpleSpritePTR
move.l SimpleSpritePTR,a0
moveq.l #-1,d0
exg a6,GraphicsBase
jsr _LVOGetSprite(a6)
exg a6,GraphicsBase
tst.l d0
bmi AbortGetSprite
move.w #43,4(SimpleSpritePTR)
clr.l 6(SimpleSpritePTR)
********** initialize newData structure used by the Sprite **********
move.w #newDataSIZE,d0
move.l #(MEMF_CLEAR!MEMF_CHIP),d1
jsr _LVOAllocMem(a6)
tst.l d0
beq AbortNewDataAlloc
movea.l d0,NewDataPTR
moveq.l #(newDataSIZE/4)-3,d0
lea 4(NewDataPTR),a0
move.l #term,d1
BEGINnewDataLOOP:
move.l d1,(a0)+
dbra d0,BEGINnewDataLOOP ;^
move.w #colon,88(NewDataPTR)
********** initialize program register variables *****************
lea buffer(pc),BufferPTR
moveq.l #AndMaskVALUE,AndMask
********************* main loop *******************
bsr.s GetSecsTillNextMin
cmpi.w #5,Secs
bpl.s DisplayTime ;V
bra.s WaitTillNextMin ;V
RESTART:
bsr.s GetSecsTillNextMin
DisplayTime:
bsr.s LoadBuffer
bsr.s GetSecsTillNextMin ;only needs to get Secs & Micros
WaitTillNextMin:
move.w Secs,2+IO_SIZE+TV_SECS(Time_ReqPTR)
move.l Micros,IO_SIZE+TV_MICRO(Time_ReqPTR)
movea.l Time_ReqPTR,a1
jsr _LVODoIO(a6)
bra RESTART ;^
***************************** SUBROUTINES **********************************
GetSecsTillNextMin:
moveq.l #SEC_PER_MIN-1,Secs
move.l #MICRO_PER_SEC-1,Micros
; get the current time
lea IOTV_SIZE(Time_ReqPTR),a1
jsr _LVODoIO(a6)
; calculate # of Secs. till next minute and put it in d0
move.l IOTV_SIZE+IO_SIZE+TV_SECS(Time_ReqPTR),d0
sub.l IOTV_SIZE+IO_SIZE+TV_MICRO(Time_ReqPTR),micros
; moveq.l #0,Temp ; clear to zero meaning AM
divu #SEC_PER_HALF,d0
; lsr.b #1,d0 ; test lsbit by shifting it into C bit
; bcc.s AM ;V
; moveq.l #12,Temp ; make it 12 if PM
; AM:
swap d0 ; d0 = # of seconds in the half day
exg d0,d1
moveq.l #0,d0
move.w d1,d0
divu #SEC_PER_MIN,d0
; swap Temp
move.w d0,Temp ; save the minutes*hrs. in half day
swap d0
sub.w d0,Secs
rts
**********************************************
LoadBuffer:
; BufferPTR = &buffer[0]
clr.l (BufferPTR)
; load buffer with the current time
moveq.l #0,d0
move.w Temp,d0 ; d0 has minutes*hrs. in half day
; clr.w Temp
; swap Temp
divu #MIN_PER_HOUR,d0
moveq.l #0,d1
add.w d0,d1 ; prepare # of hours in half day
divu #10,d1
tst.l d1
bne.s WasNot12 ;V
move.w #$0102,(bufferPTR)+
bra.s Load2and3 ;V
WasNot12:
tst.w d1
bne.s WasNotZero ;V
BlankOffset: EQU $a
move.b #BlankOffset,d1
WasNotZero:
move.b d1,(BufferPTR)+ ; buffer[0]
swap d1
move.b d1,(BufferPTR)+ ; buffer[1]
Load2and3:
swap d0
ext.l d0
divu #10,d0
move.b d0,(BufferPTR)+ ; buffer[2]
swap d0
move.b d0,(BufferPTR)+ ; buffer[3]
; BufferPTR= &buffer[3]+1
; Print Sprite
lea num4(NewDataPTR),a1
bsr.s LoadSpriteNumber
; BufferPTR= &buffer[3]
lea num3(NewDataPTR),a1
bsr.s LoadSpriteNumber
; BufferPTR= &buffer[2]
lea num2(NewDataPTR),a1
bsr.s LoadSpriteNumber
; BufferPTR= &buffer[1]
lea num1(NewDataPTR),a1
bsr.s LoadSpriteNumber
; BufferPTR= &buffer[0]
moveq.l #0,d3
move.l d3,a0
move.l SimpleSpritePTR,a1
move.l a2,-(sp)
movea.l NewDataPTR,a2
exg a6,GraphicsBase
jsr _LVOChangeSprite(a6)
move.l d3,a0
move.l SimpleSpritePTR,a1
move.l #300,d0
moveq.l #70,d1
jsr _LVOMoveSprite(a6)
move.w #3,2+IO_SIZE+TV_SECS(Time_ReqPTR) ; wait 3 Secs
; clr.l IO_SIZE+TV_MICRO(Time_ReqPTR)
exg a6,GraphicsBase
lea (Time_ReqPTR),a1
jsr _LVODoIO(a6)
exg a6,GraphicsBase
moveq.l #0,d0
move.l #244,d1
move.l d0,a0
move.l SimpleSpritePTR,a1
jsr _LVOMoveSprite(a6)
exg a6,GraphicsBase
move.l (sp)+,a2
rts
******************** LoadSpriteNumber ************************
; loads the image of the number in -(BufferPTR)
; into the memory whose first long has the address in A1.
LoadSpriteNumber:
moveq.l #0,d0
move.b -(BufferPTR),d0
asl.b #2,d0 ; multiply by 4
move.l recipeTABLE(pc,d0.w),d1
moveq.l #7,LoopCount
BEGINdecodeRecipeLOOP:
move.l d1,d0
and.w AndMask,d0
move.b imageTABLE(pc,d0.w),d0
lsl.w #4,d0
move.w d0,(a1)+
addq.l #2,a1
lsr.l #4,d1 ; get next 4-bit incoded image
dbra LoopCount,BEGINdecodeRecipeLOOP ;^
rts
imageTABLE:
DC.B twoDots
DC.B Dot1
DC.B Dot2
DC.B blank
DC.B Dot4
DC.B Dot5
DC.B Dot6
DC.B Dot7
DC.B Dot8
DC.B bar
DC.B lBar
DC.B rBar
DC.B sBar
DC.B triple
DC.B fours2Dot
DC.B onesBigDot
recipeTABLE: CNOP 0,2
zero: DC.L $c000000c
one: DC.L $d44444f4
two: DC.L $b111c88c
three: DC.L $a888c88a
four: DC.L $7779eee7
five: DC.L $c088a119
six: DC.L $c00a112f
seven: DC.L $5556788b
eight: DC.L $c000c00c
nine: DC.L $6788b00c
space: DC.L $33333333
***********************************************************************
* SECTION "initialized data",DATA
twoDots: EQU $81
Dot1: EQU $80
Dot2: EQU $40
blank: EQU $00
Dot4: EQU $10
Dot5: EQU $08
Dot6: EQU $04
Dot7: EQU $02
Dot8: EQU $01
bar: EQU $ff
lBar: EQU $fe
rBar: EQU $7f
sBar: EQU $7e
triple: EQU $38
fours2Dot: EQU $82
onesBigDot: EQU $30
colon: EQU $0440
term: EQU $7ffe
line: EQU $00
AndMaskVALUE: EQU $f
TimerPortName: CNOP 0,2
DC.B 'timer',0
Priority: EQU 0
TimerName: CNOP 0,2
DC.B 'timer.device',0
GraphicsName: CNOP 0,2
DC.B 'graphics.library',0
MICRO_PER_SEC: EQU 1000000
SEC_PER_MIN: EQU 60
MIN_PER_HOUR: EQU 60
SEC_PER_HOUR: EQU (60*60)
SEC_PER_HALF: EQU (60*60*12)
SEC_PER_DAY: EQU (60*60*24)
HOUR_PER_DAY: EQU 24
newDataSIZE: EQU 196-16
; newData offsets
num1: EQU 12
num2: EQU 52
num3: EQU 96
num4: EQU 136
* SECTION "uninitialized data",BSS
buffer: CNOP 0,2
DS.B 4
SimpleSprite: CNOP 0,2
DS.W 6
END